#pragma once
#include <stdint.h>

class Buffer {
public:
	unsigned char* data;
	unsigned char* start;
	unsigned char* max_offset;


	Buffer(unsigned int size = 5000) {
		data = new unsigned char[size];
		max_offset = data + size;
		start = data;
	}

	unsigned char read_byte() {
		return *data++;
	}

	unsigned short read_short() {
		data += 2;
		return *(data - 2) << 8 | *(data - 1);
	}

	unsigned short read_le_short() {
		data += 2;
		return *(data - 2) | *(data - 1) << 8;
	}

	unsigned int read_int() {
		data += 4;
		return *(data - 4) << 24 | *(data - 3) << 16 | *(data - 2) << 8 | *(data - 1);
	}

	int64_t read_long() {
		data += 8;
		return (int64_t)*(data - 8) << 56 | (int64_t)*(data - 7) << 48 | (int64_t)*(data - 6) << 40 | (int64_t)*(data - 5) << 32 | *(data - 4) << 24 | *(data - 3) << 16 | *(data - 2) << 8 | *(data - 1);
	}

	unsigned char read_byte_a() {
		return *data++ - 128;
	}

	unsigned char read_byte_s() {
		return *data++ + 128;
	}

	unsigned int read_smart_word() {
		if(*data < 128)
			return *data++;
		data += 2;
		return (*(data - 2) << 8) + *(data - 1) - 32768;
	}

	signed char read_signed_byte() {
		return (signed char)*data++;
	}

	signed int read_signed_short() {
		signed int u = *data++ << 8 | *data++;
		if(u >= 32768)
			u -= 0x10000;
		return u;
	}

	char* read_string() {
		int count = 0;
		while(*(data + count) != 10 && count++ < 256);
		if(count == 0)
			return "";
		char* str = new char[count + 1];
		for(int i = 0; i <= count; i++)
			str[i] = *data++;
		str[count] = 0;
		return str;
	}

	void write_byte(unsigned char c) {
		data++;
		*(data - 1) = c;
	}

	void write_word(unsigned short s) {
		*data++ = (s >> 8) & 0xff;
		*data++ = s & 0xff;
	}

	void write_int(unsigned int i) {
		*data++ = (i >> 24) & 0xff;
		*data++ = (i >> 16) & 0xff;
		*data++ = (i >> 8) & 0xff;
		*data++ = i & 0xff;
	}

	void write_long(int64_t l) {
		*data++ = (l >> 56) & 0xff;
		*data++ = (l >> 48) & 0xff;
		*data++ = (l >> 40) & 0xff;
		*data++ = (l >> 32) & 0xff;
		*data++ = (l >> 24) & 0xff;
		*data++ = (l >> 16) & 0xff;
		*data++ = (l >> 8) & 0xff;
		*data++ = l & 0xff;
	}

	~Buffer() {
		data = start;
		delete[] data;
	}
};